﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;

namespace Test
{
    public class AuYellowPage
    {
        private const string SEARCH_URL =
            "http://www.yellowpages.com.au/search/listings?clue={0}&locationClue=All+States&lat=&lon=&pageNumber={1}";

        public List<Company> Search(string category, int index)
        {
            var web = new HtmlWeb();
            string url = string.Format(SEARCH_URL, ConvertCategories(category), index);
            List<Company> result = new List<Company>();

            HtmlDocument doc = web.Load(url);
            return Companies(category, doc);
        }

        public List<Company> Search(string document,string category) {
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(document);

            return Companies(category, doc);
        }

        private List<Company> Companies(string category, HtmlDocument doc) {
            List<Company> result = new List<Company>();
            var rootClasses = new string[] {
                "flow-layout", "outside-gap-large", "inside-gap", "inside-gap-large", "vertical"
            };
            var rootXpath = BuildXPath("div", true, rootClasses);
            var gridNode = doc.DocumentNode.SelectSingleNode(rootXpath);
            if (gridNode == null) {
                return result;
            }
            var prodDiv = BuildXPath("div", false, new string[] {"cell", "middle-cell"});
            var allProds = gridNode.SelectNodes(prodDiv);

            foreach (HtmlNode node in allProds) {
                Company p = GetProductByNode(node);
                if (p != null) {
                    p.Category = category;
                    result.Add(p);
                }
            }
            return result;
        }

        private Company GetProductByNode(HtmlNode liNode) {
            var resultDiv = BuildXPath("div", false, new string[] {"listing", "listing-new-search"});
            var prodDiv = liNode.SelectSingleNode(resultDiv);
            if (prodDiv != null) {
                var company = new Company();
                var titlenode =
                    prodDiv.SelectSingleNode("./div/div/a/div[contains(@class,'srp-brand-bar-listing-name')]");
                if (titlenode == null) {
                    titlenode = prodDiv.SelectSingleNode(".//a[contains(@class,'listing-name')]");
                }
                if (titlenode != null) {
                    company.BussinessName = titlenode.InnerText
                        .Replace("&amp;", "&").Replace("&#39;","'")
                        .Replace("&#34;","\"");
                }
                var detail = prodDiv.SelectSingleNode("./div/div/div[contains(@class,'listing-details')]");
                if (detail != null) {
                    var cateCityState =
                        detail.SelectSingleNode(
                            "./div/div[contains(@class,'body') and contains(@class,'left')]/p[contains(@class,'listing-heading')]/a");
                    if (cateCityState != null) {
                        string cateCityStateStr = cateCityState.InnerText;
                        if (cateCityStateStr.LastIndexOf(",") > 0) {
                            var state = cateCityStateStr.Substring(cateCityStateStr.LastIndexOf(",") + 1);
                            cateCityStateStr = cateCityStateStr.Substring(0, cateCityStateStr.LastIndexOf(","));
                            company.State = state.Trim();
                        } else {
                            company.State = string.Empty;
                        }
                        
                        var cities = cateCityStateStr.Split('-');
                        if (cities.Length > 1) {
                            company.City = cities[1].Trim();
                        } else if(cities.Length<=1) {
                            company.City = string.Empty;
                        }
                        var address =
                            detail.SelectSingleNode(
                                "./div[contains(@class,'listing-address-container')]/span[contains(@class,'text')]/p");
                        if (address != null) {
                            var addressStr = address.InnerText.Trim();
                            var postCode = addressStr.Substring(addressStr.LastIndexOf(" ")).Trim();
                            company.StreetAddress = addressStr;
                            company.PostCode = postCode;
                        }
                    }
                }

                // Email, website, Phonenumber
                var emailRegion =
                    prodDiv.SelectSingleNode(
                        "./div/div[contains(@class,'grey')]/div[contains(@class,'primary-contacts-and-send-to-srp')]");
                if (emailRegion != null) {
                    var phone =
                        emailRegion.SelectSingleNode(
                            ".//a[contains(@class,'click-to-call') and contains(@class,'contact')]/div/span[contains(@class,'text')]/div");
                    if (phone != null) {
                        company.Phone1 = phone.InnerText.Trim();
                    }
                    var email =
                        emailRegion.SelectSingleNode(
                            ".//a[contains(@class,'contact') and contains(@class,'contact-email')]");
                    if (email != null) {
                        company.Email = email.GetAttributeValue("data-email", string.Empty);
                    }
                    var website =
                        emailRegion.SelectSingleNode(
                            ".//a[contains(@class,'contact') and contains(@class,'contact-main') and contains(@class,'contact-url')]");
                    if (website != null) {
                        company.Website = website.GetAttributeValue("href", string.Empty);
                    }
                }
                return company;
            }
            return null;
        }
        public string BuildXPath(string tag, bool fromRoot, IEnumerable<string>classnames, IEnumerable<string> ignoreClasses = null)
        {
            StringBuilder builder = new StringBuilder();
            if (fromRoot)
            {
                builder.Append("//");
            }
            else
            {
                builder.Append("./");
            }
            if (string.IsNullOrEmpty(tag))
            {
                builder.Append("*");
            }
            else
            {
                builder.Append(tag);
            }
            builder.Append("[");
            int index = 0;
            foreach (var classname in classnames)
            {
                builder.Append("contains(@class,'" + classname.Trim() + "'");
                index++;
                if (index < classnames.Count())
                {
                    builder.Append(") and ");
                }
            }
            index = 0;
            if (ignoreClasses != null && ignoreClasses.Count() > 0) {
                builder.Append(") and ");
                foreach (var classname in ignoreClasses)
                {
                    builder.Append("not(contains(@class,'" + classname.Trim() + "')");
                    index++;
                    if (index < ignoreClasses.Count())
                    {
                        builder.Append(") and ");
                    }
                }
            }
            builder.Append(")]");

            return builder.ToString();
        }

        private string ConvertCategories(string cate) {
            cate = cate.Replace(" ", "+");
            cate = cate.Replace("&", "%26");
            return cate;
        }

    }

    public class MountInformation {
        public string MountName { get; set; }
        public string AreaName { get; set; }
        public string Height { get; set; }
        public string Coordinates { get; set; }
        public string Prominence { get; set; }
        public string LineParent { get; set; }
        public string NTSMapsheet { get; set; }
        public string NameStatus { get; set; }
        public string FirstAscent { get; set; }
    }

    public class Company
    {
        public string Category { get; set; }
        public string BussinessName { get; set; }
        public string StreetAddress { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostCode { get; set; }
        public string Phone1 { get; set; }
        public string Phone2 { get; set; }
        public string Website { get; set; }
        public string Email { get; set; }
    }
}
